<script>

import { useDictData } from '@/api/system/dict'
import { isEmpty } from 'lodash'

export default {
  name: 'FormWrap',
  model: {
    value: 'ctx',
    event: 'change'
  },
  props: {
    element: {
      type: Object,
      default: () => {
      }
    },
    dictType: {
      type: String,
      default: null
    },
    gutter: {
      type: Number,
      default: 24
    },
    ctx: {
      type: Object,
      default: () => {
      }
    },
    size: {
      type: String,
      default: 'default'
    },
    isDesign: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      data: null
    }
  },
  watch: {
    'ctx.data': {
      handler(val) {
        this.data = val
      }
    },
    dictType: {
      handler() {
        this.getDictData()
      },
      immediate: true,
      deep: true
    }
  },
  created() {
    this.data = this.ctx.data
  },
  methods: {
    getDictData() {
      if (!isEmpty(this.dictType)) {
        useDictData(this.dictType).then(resp => {
          this.element.options = resp.data || []
        })
      }
    },
    callAttributes() {
      return this.element.attributes
    },
    blurEvent(element) {
      this.processElement(element)
      const event = element.blurEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    focusEvent(element) {
      if (this.isDesign) {
        console.log('publish click-element event')
        this.publishEvent('clickElement', element)
      }
      const event = element.focusEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    changeEvent(element) {
      this.processElement(element)
      const event = element.changeEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    changeEventCall(val, element) {
      this.data[element.name] = val
      this.processElement(element)
      const event = element.changeEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    clickEvent(element) {
      const event = element.clickEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    inputEvent(element) {
      const event = element.inputEvent
      if (event) {
        this.dispatchEvent(event, element)
      }
    },
    dispatchEvent(event, element) {
      if (event) {
        console.log('exec ' + event + ' event')
        this.publishEvent(event, element)
        this.executeEvent(event, element)
      }
    },
    processElement(element) {
      /* 解析依赖关系 */
      this.processDepend()
      /* 解析变量 */
      this.processVariable(element)
    },
    processDepend() {
      this.$emit('depends')
    },
    processVariable(element) {
      const isVariable = element.isVariable
      if (isVariable) {
        const name = element.name
        const value = this.data[name]
        this.ctx.vars[name] = value
        console.log(name + ' data => var ' + value)
      }
    },
    publishEvent(event, element) {
      this.$emit(event, element, this.ctx)
    },
    executeEvent(event, element) {
      const definitionEvent = this.getDefinitionEvents(event)
      if (definitionEvent && typeof definitionEvent === 'function') {
        definitionEvent.bind(this)(element, this.ctx)
      }
    },
    getDefinitionEvents(event) {
      return {}[event]
    }
  }
}
</script>

<template>

  <el-form-item
    :label="element.label"
    :prop="element.prop"
    :rules="element.rules"
    :error="element.error"
    :required="element.required"
    :label-width="element.labelWidth"
    :prop-name="element.propName"
  >
    <template v-if="element.type === 'input'">
      <el-input
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :placeholder="element.placeholder"
        :disabled="element.disabled"
        :size="size || 'small'"
        :clearable="element.clearable"
        :readonly="element.readonly"
        :prefix-icon="callAttributes().prefixIcon"
        :suffix-icon="callAttributes().suffixIcon"
        :show-password="callAttributes().showPassword"
        :autosize="callAttributes().autosize"
        :type="element.type"
        :maxlength="callAttributes().maxlength"
        :minlength="callAttributes().minlength"
        :show-word-limit="callAttributes().showWordLimit"
        :rows="callAttributes().rows"
        :cols="callAttributes().cols"
        @blur="()=> blurEvent(element)"
        @focus="()=> focusEvent(element)"
        @input="()=> inputEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'textarea'">
      <el-input
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :placeholder="element.placeholder"
        :disabled="element.disabled"
        :size="size"
        :prefix-icon="callAttributes().prefixIcon"
        :suffix-icon="callAttributes().suffixIcon"
        :clearable="element.clearable"
        :readonly="element.readonly"
        :autosize="callAttributes().autosize"
        :type="element.type"
        :maxlength="callAttributes().maxlength"
        :minlength="callAttributes().minlength"
        :show-word-limit="callAttributes().showWordLimit"
        :rows="callAttributes().rows"
        :cols="callAttributes().cols"
        @blur="()=> blurEvent(element)"
        @focus="()=> focusEvent(element)"
        @input="()=> inputEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'number'">
      <el-input-number
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :placeholder="element.placeholder"
        :disabled="element.disabled"
        :size="size"
        :prefix-icon="callAttributes().prefixIcon"
        :suffix-icon="callAttributes().suffixIcon"
        :clearable="element.clearable"
        :controls="callAttributes().controls"
        :min="callAttributes().min"
        :max="callAttributes().max"
        :step="callAttributes().step"
        :precision="callAttributes().precision"
        @blur="()=> blurEvent(element)"
        @focus="()=> focusEvent(element)"
        @input="()=> inputEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'date'">
      <el-date-picker
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :type="element.type"
        :placeholder="element.placeholder"
        :format="callAttributes().format"
        :value-format="callAttributes().valueFormat"
        :disabled="element.disabled"
        :size="size"
        :editable="callAttributes().editable"
        :clearable="element.clearable"
        :default-time="callAttributes().defaultTime"
        :start-placeholder="callAttributes().startPlaceholder"
        :end-placeholder="callAttributes().endPlaceholder"
        :range-separator="callAttributes().rangeSeparator"
        :picker-options="callAttributes().pickerOptions"
        @focus="()=> focusEvent(element)"
        @blur="()=> blurEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'time'">
      <el-time-picker
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :placeholder="element.placeholder"
        :format="callAttributes().format"
        :value-format="callAttributes().valueFormat"
        :disabled="element.disabled"
        :size="size"
        :editable="callAttributes().editable"
        :clearable="element.clearable"
        :default-time="callAttributes().defaultTime"
        :start-placeholder="callAttributes().startPlaceholder"
        :end-placeholder="callAttributes().endPlaceholder"
        :range-separator="callAttributes().rangeSeparator"
        :picker-options="callAttributes().pickerOptions"
        @focus="()=> focusEvent(element)"
        @blur="()=> blurEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'datetime'">
      <el-date-picker
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :type="element.type"
        :placeholder="element.placeholder"
        :format="element.format"
        :value-format="element.valueFormat"
        :disabled="element.disabled"
        :size="size"
        :editable="callAttributes().editable"
        :clearable="callAttributes().clearable"
        :default-time="callAttributes().defaultTime"
        :start-placeholder="callAttributes().startPlaceholder"
        :end-placeholder="callAttributes().endPlaceholder"
        :range-separator="callAttributes().rangeSeparator"
        :picker-options="callAttributes().pickerOptions"
        @focus="()=> focusEvent(element)"
        @blur="()=> blurEvent(element)"
        @change="()=> changeEvent(element)"
      />
    </template>
    <template v-if="element.type === 'select'">
      <el-select
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :placeholder="element.placeholder"
        :multiple="element.multiple"
        :disabled="element.disabled"
        :clearable="element.clearable"
        :size="size"
        :popper-class="callAttributes().popperClass"
        :multiple-limit="callAttributes().multipleLimit"
        @change="(val)=> changeEventCall(val,element)"
        @blur="() => blurEvent(element)"
        @focus="()=> focusEvent(element)"
      >
        <el-option
          v-for="item in element.options"
          :key="item.value"
          :label="item.dictLabel"
          :value="item.dictValue"
        />
      </el-select>
    </template>
    <template v-if="element.type === 'cascader'">
      <el-cascader
        v-model="data[element.name]"
        :style="{width: element.width || '100%'}"
        :options="element.options"
        :props="element.props"
        :placeholder="element.placeholder"
        :disabled="element.disabled"
        :clearable="element.clearable"
        :size="size"
        :popper-class="element.popperClass"
        :multiple-limit="element.multipleLimit"
        :clear-icon="element.clearIcon"
        @change="(val)=> changeEventCall(val,element)"
        @blur="() => blurEvent(element)"
        @focus="()=> focusEvent(element)"
      />
    </template>
    <template v-if="element.type === 'radio'">
      <el-radio-group
        v-model="data[element.name]"
        :disabled="element.disabled"
        :size="size"
        :fill="element.fill"
        :text-color="element.textColor"
        :border-color="element.borderColor"
        @input="() => changeEvent(element)"
      >
        <el-radio
          v-for="(item, index) in element.options"
          :key="index"
          :label="item.dictValue"
          :disabled="item.disabled"
          :border="element.border"
        >{{ item.dictLabel }}
        </el-radio>
      </el-radio-group>
    </template>
    <template v-if="element.type === 'checkbox'">
      <el-checkbox-group
        :style="{width: element.width || '100%'}"
        :disabled="element.disabled"
        :size="size"
        :fill="element.fill"
        :text-color="element.textColor"
        :border-color="element.borderColor"
        @change="(val) => changeEventCall(val,element)"
        @focus="()=> focusEvent(element)"
      >
        <el-checkbox
          v-for="(item, index) in element.options"
          :key="index"
          :label="item.dictValue"
          :disabled="item.disabled"
          :border="element.border"
        >{{ item.dictLabel }}
        </el-checkbox>
      </el-checkbox-group>
    </template>
  </el-form-item>
</template>

<style scoped lang="scss">

</style>
